import type { ComponentStyleIdType, PlatformTypeValue } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import { PageHandler } from '../../../lib/page_handler'
import { GiteePageType } from '../../../lib/page_handler/platform/gitee/types'
import { PollingHandler } from '../../../lib/polling_handler'
import {
  ComponentStyleId,
  HOSTNAME,
  logger,
  PROJECT_PREFIX,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'
import { ConfigManager } from '../../config_manager'

interface Config {
  enabled?: boolean
}

interface CommitIconsConfig {
  selector: string | string[]
  mergeRecognize?: ($element: JQuery<HTMLElement>) => boolean
  listen?: boolean
}

type CommitIconsPlatformConfig = Partial<Record<PlatformTypeValue, Record<string, CommitIconsConfig>>>

export interface CommitMetadata {
  type: CommitType
  icon: string
  color?: string
  description: string
}
export interface CommitTypeMapping extends CommitMetadata {
  pattern: RegExp
  color?: string
}

export enum CommitType {
  PREF = 'perf',
  FEAT = 'feat',
  FIX = 'fix',
  DOCS = 'docs',
  STYLE = 'style',
  REFACTOR = 'refactor',
  TEST = 'test',
  CHORE = 'chore',
  MERGE = 'merge',
  OTHER = 'other',
}

export interface CommitIconInfo {
  element: JQuery<HTMLElement>
  commitType: CommitType
  icon: string
  originalText: string
}

/**
 * 默认文件图标配置
 */
const DEFAULT_COMMIT_ICONS: CommitMetadata = {
  icon: SYMBOLS.STATUS.INFO,
  type: CommitType.OTHER,
  color: '#9E9E9E',
  description: '其他提交',
}

/**
 * 配置提交图标类型映射
 */
const COMMIT_TYPE_MAPPINGS: CommitTypeMapping[] = [
  // 其他提交类型
  { pattern: /^(perf(ormance)?)(\([^)]+\))?:/i, icon: SYMBOLS.UI.SETTINGS, type: CommitType.PREF, color: '#FF6B35', description: '性能优化' },
  { pattern: /^(feat(ure)?)(\([^)]+\))?:/i, icon: SYMBOLS.STATUS.SPARKLES, type: CommitType.FEAT, color: '#4CAF50', description: '新功能' },
  { pattern: /^(fix|bugfix)(\([^)]+\))?:/i, icon: SYMBOLS.NATURE.INSECT, type: CommitType.FIX, color: '#F44336', description: 'Bug 修复' },
  { pattern: /^(docs|documentation)(\([^)]+\))?:/i, icon: SYMBOLS.DOCUMENTS.MEMO, type: CommitType.DOCS, color: '#2196F3', description: '文档更新' },
  { pattern: /^(style|css|ui)(\([^)]+\))?:/i, icon: SYMBOLS.OTHERS.PALETTE, type: CommitType.STYLE, color: '#9C27B0', description: '样式更新' },
  { pattern: /^(refactor(ing)?)(\([^)]+\))?:/i, icon: SYMBOLS.UI.CONSTRUCTION, type: CommitType.REFACTOR, color: '#FF9800', description: '代码重构' },
  { pattern: /^(test(ing)?)(\([^)]+\))?:/i, icon: SYMBOLS.UI.TEST, type: CommitType.TEST, color: '#009688', description: '测试相关' },
  { pattern: /^(chore|config|build)(\([^)]+\))?:/i, icon: SYMBOLS.UI.SETTINGS, type: CommitType.CHORE, color: '#607D8B', description: '配置变更' },
  { pattern: /^(ci|cd|pipeline)(\([^)]+\))?:/i, icon: SYMBOLS.UI.SETTINGS, type: CommitType.OTHER, color: '#1976D2', description: 'CI/CD' },
  { pattern: /^(deps|dependencies)(\([^)]+\))?:/i, icon: SYMBOLS.UI.PACKAGE, type: CommitType.OTHER, color: '#1565C0', description: '依赖更新' },
  { pattern: /^(sec(urity)?)(\([^)]+\))?:/i, icon: SYMBOLS.NETWORK.SHIELD, type: CommitType.OTHER, color: '#C62828', description: '安全修复' },
  { pattern: /^(revert|rollback)(\([^)]+\))?:/i, icon: SYMBOLS.ARROWS.BACK, type: CommitType.OTHER, color: '#5D4037', description: '回滚操作' },
  { pattern: /^(merge|merging)(\([^)]+\))?:/i, icon: SYMBOLS.STATUS.REFRESH, type: CommitType.MERGE, color: '#7B1FA2', description: '分支合并' },
  { pattern: /^(release|version)(\([^)]+\))?:/i, icon: SYMBOLS.UI.TAG, type: CommitType.OTHER, color: '#FFA000', description: '版本发布' },

  // 默认提交类型（最后匹配）
  { pattern: /.*/, ...DEFAULT_COMMIT_ICONS },
]

export class CommitIcons extends BaseModule {
  readonly id: string = 'commit_icons'
  readonly styleId: string = ComponentStyleId[this.name]
  isInitialized: boolean = false
  private static instance: CommitIcons
  private readonly className: string = `${PROJECT_PREFIX}-commit-icon`
  private readonly configManager: ConfigManager = ConfigManager.getInstance()
  readonly supportedPlatforms: string[] = this.configManager.moduleSupportedPlatforms(this.name)

  get currentConfig(): CommitIconsConfig | undefined {
    return this.getCurrentConfig()
  }

  // 存储处理过的提交信息
  private processedCommits: Map<JQuery<HTMLElement>, CommitIconInfo> = new Map()

  config: Config = {
    enabled: true,
  }

  get name(): ComponentStyleIdType {
    return 'CommitIcons'
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): CommitIcons {
    if (!CommitIcons.instance) {
      CommitIcons.instance = new CommitIcons()
    }
    return CommitIcons.instance
  }

  handleCleanupOthers(): void {
    this.unregisterStyle(this.styleId)
    this.cleanup()
  }

  handleCleanupReferences(): void {
    this.processedCommits.clear()
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.applyCommitIcons()

    // 注册样式
    this.registerStyle(this.styleId, this.getStyles())
  }

  onToggleCallback(_id: string, checked: boolean, first: boolean): void {
    super.onToggleCallback(_id, checked, first)
  }

  /**
   * 获取当前页面的配置
   */
  getCurrentConfig(): CommitIconsConfig | undefined {
    const config: CommitIconsPlatformConfig = {
      [SUPPORTED_PLATFORMS.GITEE]: {
        [GiteePageType.Project]: {
          selector: [
            '#tree-content-holder .recent-commit .repo-index-commit-msg',
            '#tree-slider .tree-item .commit-details .tree-commit-link',
          ],
          mergeRecognize: ($element: JQuery<HTMLElement>) => {
            const title = $element.attr('title') || ''
            return /Merge/i.test(title) || false
          },
          listen: true,
        },
        [GiteePageType.Commits]: {
          selector: '#commits-list .commit-group .commit-show-message .tree-commit-link',
          mergeRecognize: ($element: JQuery<HTMLElement>) => {
            const title = $element.attr('title') || ''
            return /Merge/i.test(title) || false
          },
        },
        [GiteePageType.CodeView]: {
          selector: '#tree-content-holder .recent-commit > a:last-of-type',
          mergeRecognize: ($element: JQuery<HTMLElement>) => {
            const title = $element.attr('title') || ''
            return /Merge/i.test(title) || false
          },
        },
      },
    }

    const currentConfig = config[HOSTNAME]?.[PageHandler.getCurrentPageType()]

    if (!currentConfig) {
      logger.warn(`[${this.name}] 未找到当前页面类型的配置`)
    }

    return currentConfig
  }

  applyCommitIcons(): void {
    if (!this.currentConfig)
      return

    this.cleanup()

    const { selector, listen } = this.currentConfig

    const handler = () => {
      const fullSelector = Array.isArray(selector) ? selector.join(', ') : selector
      const $elements = $(fullSelector)
      const elementCount = $elements.length

      if (elementCount === 0) {
        logger.notice(`[${this.name}] ${SYMBOLS.STATUS.WARNING} 未找到提交元素，跳过处理`, fullSelector)
        return
      }

      $elements.each((_index, element) => {
        const $element = $(element)

        this.processCommitElement($element)
      })

      logger.info(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} 已为 ${elementCount} 个提交添加图标`)
    }

    if (!listen) {
      handler()
    }
    else {
      const pollingHandler = new PollingHandler()
      pollingHandler.api.awaitElement(selector, handler)
    }
  }

  /**
   * 处理提交元素
   */
  processCommitElement($element: JQuery<HTMLElement>): void {
    const description = $element.text()?.trim() || ''

    if (!description) {
      logger.info(`[${this.name}] 提交描述为空，跳过处理`)
      return
    }

    const commitInfo = this.getCommitInfo($element, description)
    this.addIconToElement($element, commitInfo)
  }

  /**
   * 获取提交信息
   */
  private getCommitInfo($element: JQuery<HTMLElement>, description: string): { type: CommitType, icon: string, description: string } {
    // 检查预设映射
    for (const mapping of COMMIT_TYPE_MAPPINGS) {
      if (mapping.pattern.test(description)) {
        return mapping
      }
      else if (mapping.type === CommitType.MERGE && this.currentConfig?.mergeRecognize?.($element)) {
        return mapping
      }
    }

    // 默认提交类型
    return DEFAULT_COMMIT_ICONS
  }

  /**
   * 添加图标到元素
   */
  private addIconToElement($element: JQuery<HTMLElement>, metadata: CommitMetadata): void {
    const { type, icon, color = '' } = metadata

    this.removeExistingIcon($element)

    // 移除图标文本
    const originalText = $element.text().trim()
    const cleanedText = originalText.replace(icon, '')

    $element
      .addClass(`${this.className} ${type}`)
      .text(cleanedText)
      .css('color', color)

    this.processedCommits.set($element, {
      element: $element,
      commitType: type,
      icon,
      originalText,
    })
  }

  /**
   * 移除现有图标
   */
  private removeExistingIcon($element: JQuery<HTMLElement>): void {
    $element.removeClass(`${this.className} ${Object.values(CommitType).join(' ')}`)
  }

  /**
   * 清理操作
   */
  private cleanup(): void {
    this.processedCommits.forEach((info, element) => {
      this.removeExistingIcon(element)

      // 恢复原始文本
      element.text(info.originalText)
    })
    this.processedCommits.clear()
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.applyCommitIcons()

    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }

  getStyles(): string {
    return `
.${this.className} {
  transition: all 0.3s ease;
  
  &:hover {
    color: var(${this.themeVarService.link.default.text}) !important;
  }
  
  ${Object.values(COMMIT_TYPE_MAPPINGS).map(mapping => `&.${mapping.type}::before {
    content: '${mapping.icon}';
    margin-right: 4px;
  }`).join('\n')}
}    
    `
  }
}
